/**
 * 供带明细的详情页使用
 */

import {computed, ComputedRef, reactive, Ref, ref} from 'vue'
import _ from 'lodash'
import {useI18n} from 'vue-i18n'

enum PageMode {
  View = 'view',
  Create = 'create',
  Edit = 'edit'
}

// 跳转方法
interface LineDetailNav {
  // 回到列表Tab
  backToListTab: () => void,
  // 明细详情转到查看模式(取消编辑)
  turnLineToViewMode: () => void
  // 明细详情转到编辑模式(转入编辑)
  turnLineToEditMode: () => void
  // 取消新建/编辑(可能返回列表，也可能进入查看)
  cancelLineSubmit: () => void
  // 完成编辑提交(可能返货列表，也可能进入查看)
  doneLineEdit: () => void
  // 创建明细
  goCreateLine: (initModel: Record<string, any>) => void
  // 编辑明细
  goEditLine: (lineItemId: string | number) => void
  // 查看明细
  goViewLine: (lineItemId: string | number) => void
}

// 明细数据详情(reactive)
interface LineDetailInfo {
  // 当前的ID，loadLineModelData就是或者这个ID的数据
  lineItemId: string | number | null,
  // 明细Model数据， loadLineModelData时给它赋值
  lineForm: Record<string, any>
}

interface LineDetailStatus {
  // 判断页面模式是否为查看
  isLineViewMode: ComputedRef<boolean>
  // 判断页面模式是否为新建
  isLineCreateMode: ComputedRef<boolean>
  // 判断页面模式是否为编辑
  isLineEditMode: ComputedRef<boolean>
  // 判断页面模式是否为新建或编辑(修改模式)
  isLineCreateOrEditMode: ComputedRef<boolean>
  // 判断页面模式是否为查看或编辑(条目已存在)
  isLineViewOrEditMode: ComputedRef<boolean>
  // 明细详情Tab是否显示
  isLineTabDisp: ComputedRef<boolean>
  // Tab应当显示的标题
  tabTitle: ComputedRef<string>
}

// LineDetail页返回定义
interface LineDetailSuite {
  // 明细数据详情(reactive)
  lineDetailInfo: LineDetailInfo
  // 明细数据详情(reactive)
  lineDetailStatus: LineDetailStatus
  // 导航帮助方法
  lineDetailNav: LineDetailNav
}

// 在created生命周期函数中调用此方法
// lineName: 关键参数，通过它来访问内部数据(考虑到一个详情页可能有多种明细，这个lineName就相当于一个访问key)
// lineDispName: 用于在Tab上显示名称为: "XXX详情"/"新建XXX"/"编辑XXX"
// lineListPanelName: 展示这个明细的列表的tab是哪一个
// lineFormSkeleton: 表单骨架，如果表单中包含额外的结构，通常需要提供一个“骨架”以防出现undefined的问题
export function useLineDetailHelper(
  // 显示在Tab上的标题
  lineDispName: string,
  // 用来展示明细列表的Tab的名称
  lineListPanelName: string,
  // 用来展示明细详情的Tab的名称
  lineDetailPanelName: string,
  // 表单骨架，如果表单中包含额外的结构，通常需要提供一个“骨架”以防出现undefined的问题
  lineFormSkeleton: Record<string, any> | null,
  // 加载数据，初始时以及进入view模式后会用此方法load数据
  loadLineModelData: () => void,
  // 当前正在显示的Tab
  showingTabPanel: Ref<string>,
  // 显示在banner上的错误信息
  serverErrorMessage: Ref<string> | null,
  // 用此方法Reset验证对象状态，验证对象可能在useLineDetailHelper之后生成，所以不能直接将vuelidate对象作为参数传入(鸡生蛋蛋生鸡的问题)
  // 于是就用这延迟执行的办法
  resetValObj: ()=>void | null): LineDetailSuite {

  // 取消是否返回明细列表tab
  const needBackToListOnCancel = ref(false)

  // 明细详情页当前状态(''表示不显示)
  const linePageMode = ref('')

  // 数据
  const lineDetailInfo: LineDetailInfo = reactive({
    lineForm: {},
    lineItemId: null
  })

  const setServerErrorMessage = function (errorMessage: string) {
    if (serverErrorMessage) {
      serverErrorMessage.value = errorMessage
    }
  }

  const backToListTab = function () {
    // 清除原先的错误信息(如果有的话)
    setServerErrorMessage('')
    // 显示列表页
    if (showingTabPanel.value === lineDetailPanelName) {
      showingTabPanel.value = lineListPanelName
    }
    // 关闭本Tab页
    linePageMode.value = ''
  }

  // 明细详情转到查看模式(取消编辑)
  const turnLineToViewMode = function () {
    setServerErrorMessage('')
    linePageMode.value = PageMode.View
    loadLineModelData()
  }
  // 明细详情转到编辑模式(转入编辑)
  const turnLineToEditMode = function () {
    linePageMode.value = PageMode.Edit
  }

  // 取消新建/编辑(可能返回列表，也可能进入查看)
  const cancelLineSubmit = function () {
    if (needBackToListOnCancel.value) {
      backToListTab()
    } else {
      turnLineToViewMode()
    }
  }

  // 完成编辑提交(可能返货列表，也可能进入查看)
  const doneLineEdit = function () {
    if (needBackToListOnCancel.value) {
      backToListTab()
    } else {
      turnLineToViewMode()
    }
  }

  // 创建明细
  const goCreateLine = function (initModel: Record<string, any>) {
    needBackToListOnCancel.value = true
    linePageMode.value = PageMode.Create
    showingTabPanel.value = lineDetailPanelName
    if (initModel) {
      lineDetailInfo.lineForm = _.cloneDeep(initModel)
      if(resetValObj){
        resetValObj()
      }
    }
  }

  // 编辑明细
  const goEditLine = function (lineItemId: string | number) {
    needBackToListOnCancel.value = true
    lineDetailInfo.lineForm = lineFormSkeleton ? _.cloneDeep(lineFormSkeleton) : {}
    if(resetValObj){
      resetValObj()
    }
    lineDetailInfo.lineItemId = lineItemId
    linePageMode.value = PageMode.Edit
    showingTabPanel.value = lineDetailPanelName
    loadLineModelData()
  }

  // 查看明细
  const goViewLine = function (lineItemId: string | number) {
    needBackToListOnCancel.value = false
    lineDetailInfo.lineForm = lineFormSkeleton ? _.cloneDeep(lineFormSkeleton) : {}
    if(resetValObj){
      resetValObj()
    }
    lineDetailInfo.lineItemId = lineItemId

    linePageMode.value = PageMode.View
    showingTabPanel.value = lineDetailPanelName
    loadLineModelData()
  }

  // 判断页面模式是否为查看
  const isLineViewMode = computed(() => linePageMode.value === PageMode.View)
  // 判断页面模式是否为新建
  const isLineCreateMode = computed(() => linePageMode.value === PageMode.Create)
  // 判断页面模式是否为编辑
  const isLineEditMode = computed(() => linePageMode.value === PageMode.Edit)
  // 判断页面模式是否为新建或编辑(修改模式)
  const isLineCreateOrEditMode = computed(() => linePageMode.value === PageMode.Create || linePageMode.value === PageMode.Edit)
  // 判断页面模式是否为查看或编辑(条目已存在)
  const isLineViewOrEditMode = computed(() => linePageMode.value === PageMode.View || linePageMode.value === PageMode.Edit)
  // 详情Tab是否显示
  const isLineTabDisp = computed(() => !!linePageMode.value)
  // 注入多语言
  const {t, locale} = useI18n()
  // 显示在Tab上的标题
  const tabTitle = computed(() => {
    switch (linePageMode.value) {
      case PageMode.View:
        return lineDispName + (locale.value==='zh-CN'?'': ' ') + t('详情')
      case PageMode.Create:
        return t('新建') + (locale.value==='zh-CN'?'': ' ') + lineDispName
      case PageMode.Edit:
        return t('编辑') + (locale.value==='zh-CN'?'': ' ') + lineDispName
      default:
        return ''
    }
  })

  const lineDetailStatus = {
    isLineViewMode,
    isLineCreateMode,
    isLineEditMode,
    isLineCreateOrEditMode,
    isLineViewOrEditMode,
    isLineTabDisp,
    tabTitle
  }

  const lineDetailNav = {
    backToListTab,
    turnLineToViewMode,
    turnLineToEditMode,
    cancelLineSubmit,
    doneLineEdit,
    goCreateLine,
    goEditLine,
    goViewLine
  }

  return {
    lineDetailInfo,
    lineDetailStatus,
    lineDetailNav
  }
}
